package com.genexususa.eo.connection.google.analytics;

import com.google.api.client.googleapis.json.GoogleJsonError;
import com.google.api.client.googleapis.json.GoogleJsonResponseException;
import com.google.api.services.analytics.Analytics;
import com.google.api.services.analytics.model.*;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;


/**
 * Created with IntelliJ IDEA.
 * User: Nico
 * Date: 19/07/13
 * Time: 04:04 PM
 * To change this template use File | Settings | File Templates.
 */
public class AnalyticsManager {

    private static final String FILE_PATH = "filePath";
    private static final String APPLICATION_NAME = "applicationName";
    private static final String PROFILE_ID = "profileId";
    private static final String START_DATE = "startDate";
    private static final String END_DATE = "endDate";
    private static final String METRICS = "metrics";
    private static final String DIMENSIONS = "dimensions";
    private static final String SORTS = "sorts";
    private static final String FILTERS = "filters";
    private static final String MAX_RESULTS = "maxResults";


    private static boolean setCredentials = false;
    private static String dataStoreDir = "";
    private static String clientSecrets = "";


    public void setCredentials(String dataStore, String clientSecrets){
        this.setCredentials = true;
        this.dataStoreDir = dataStore;
        this.clientSecrets = clientSecrets;
    }


    public AnalyticsManager(){
        this.setCredentials = false;
        this.dataStoreDir = "";
        this.clientSecrets = "";

        setCredentials(".store/analytics_sample", "/client_secrets.json");
    }



    /**
     * Connects to Google Analytics
     * Parses the input XML
     * Runs Query on Google Analytics
     * And returns the result as a GXSDT.toxml() string
     *
     * @param xml
     * @return
     */
    public String executeQuery(String xml){

        String result = "";
        String filePath = "";
        String profileId = "";

        try{

            // Parse xml with Query parameters
            GoogleAnalyticsQuery queryParams = parseXML(xml);

            filePath = queryParams.getFilePath();
            String applicationName = queryParams.getApplicationName();
            profileId = queryParams.getProfileId();
            String startDate = queryParams.getStartDate();
            String endDate = queryParams.getEndDate();
            List<String> metrics = queryParams.getMetrics();
            List<String> dimensions = queryParams.getDimensions();
            List<String> filters = queryParams.getFilters();
            List<String> sortsCol = queryParams.getSortsCol();
            int maxResults = queryParams.getMaxResults();

            // connect to google analytics
            AnalyticsConnector ac = AnalyticsConnector.getInstance();

            if (setCredentials){
                ac.setCredentials(dataStoreDir, clientSecrets);
            }


            // execute query
            GaData queryResult = ac.executeQuery(applicationName, profileId, startDate, endDate, metrics, dimensions, filters, sortsCol, maxResults);

            printQueryInfo(queryResult);
            System.out.println();
            printDataTable(queryResult);

            printTotalsForAllResults(queryResult);

            result = resultToXml(queryResult);
            writeXMLFile(filePath, profileId, result);

            System.out.println();
            System.out.println("Result XML:");
            System.out.println(result);


        }catch (GoogleJsonResponseException e) {

            GoogleAnalyticsResult gaResult = new GoogleAnalyticsResult();
            gaResult.HasError = true;

            GoogleJsonError gaError = e.getDetails();

            ErrorsStruct errors  = new ErrorsStruct();
            errors.Message = gaError.getMessage();
            errors.Code = Integer.toString(gaError.getCode());

            List<GoogleJsonError.ErrorInfo> errorInfoCol =  gaError.getErrors();

            errors.Errors = new ArrayList<Error>();

            for(GoogleJsonError.ErrorInfo errorInfo : errorInfoCol){

                Error error = new Error();
                error.Domain = errorInfo.getDomain();
                error.Reason = errorInfo.getReason();
                error.Message = errorInfo.getMessage();
                error.LocationType = errorInfo.getLocationType();
                error.Location = errorInfo.getLocation();

                errors.Errors.add(error);

            }

            gaResult.Errors = errors;

            result = objectToXML(gaResult);
            writeXMLFile(filePath, profileId, result);
            System.err.println(result);

            return result;

        }catch (Exception e){

            GoogleAnalyticsResult gaResult =  new GoogleAnalyticsResult();
            gaResult.HasError = true;

            ErrorsStruct errors  = new ErrorsStruct();
            errors.UnknownError = e.getMessage();

            gaResult.Errors = errors;
            //e.printStackTrace();

            result = objectToXML(gaResult);
            writeXMLFile(filePath, profileId, result);
            System.err.println(result);

            return result;
        }


        return result;
    }

    public String getTop10Keywords(String xml){

        String result = "";
        String profileId = "";
        String filePath = "";
        String accountId = "";

        try{

            // Parse xml with Query parameters
            GoogleAnalyticsQuery queryParams = parseXML(xml);

            filePath = queryParams.getFilePath();
            String applicationName = queryParams.getApplicationName();
            profileId = queryParams.getProfileId();
            String startDate = queryParams.getStartDate();
            String endDate = queryParams.getEndDate();
            String query = queryParams.getQuery();
            Long analyticsImportId = queryParams.getAnalyticsImportId();

            List<String> metrics = queryParams.getMetrics();
            List<String> dimensions = queryParams.getDimensions();
            List<String> filters = queryParams.getFilters();
            List<String> sortsCol = queryParams.getSortsCol();
            int maxResults = queryParams.getMaxResults();



            // connect to google analytics
            AnalyticsConnector ac = AnalyticsConnector.getInstance();

            if (setCredentials){
                ac.setCredentials(dataStoreDir, clientSecrets);
            }


            // execute query
            GaData queryResult = ac.executeQuery(applicationName, profileId, startDate, endDate, metrics, dimensions, filters, sortsCol, maxResults);

            result = top10resultToXML(queryResult);

            //MySQLAccess mySQL = new MySQLAccess();
            //int id = mySQL.insertRow(query, profileId, accountId, java.sql.Date.valueOf(startDate), java.sql.Date.valueOf(endDate), "");

            //mySQL.updateRow(analyticsImportId, query, profileId, accountId, java.sql.Date.valueOf(startDate), java.sql.Date.valueOf(endDate), result);

            writeXMLFile(filePath, profileId, result);

            // prints to console
            printQueryInfo(queryResult);
            System.out.println();
            printDataTable(queryResult);
            System.out.println();
            System.out.println("Result XML:");
            System.out.println(result);

            return result;

        }catch (GoogleJsonResponseException e) {

            Top10KeywordsResult gaResult = new Top10KeywordsResult();
            gaResult.HasError = true;

            GoogleJsonError gaError = e.getDetails();

            ErrorsStruct errors  = new ErrorsStruct();
            errors.Message = gaError.getMessage();
            errors.Code = Integer.toString(gaError.getCode());

            List<GoogleJsonError.ErrorInfo> errorInfoCol =  gaError.getErrors();

            errors.Errors = new ArrayList<Error>();

            for(GoogleJsonError.ErrorInfo errorInfo : errorInfoCol){

                Error error = new Error();
                error.Domain = errorInfo.getDomain();
                error.Reason = errorInfo.getReason();
                error.Message = errorInfo.getMessage();
                error.LocationType = errorInfo.getLocationType();
                error.Location = errorInfo.getLocation();

                errors.Errors.add(error);

            }

            gaResult.Errors = errors;

            result = objectToXML(gaResult);
            System.err.println(result);

            return result;

        }catch (Exception e){

            Top10KeywordsResult gaResult =  new Top10KeywordsResult();
            gaResult.HasError = true;

            ErrorsStruct errors  = new ErrorsStruct();
            errors.UnknownError = e.getMessage();

            gaResult.Errors = errors;

            result = objectToXML(gaResult);
            System.err.println(result);

            return result;
        }



    }

    public String getConversions(String xml) {

        String result = "";
        String filePath = "";
        String profileId = "";

        try{

            // Parse xml with Query parameters
            GoogleAnalyticsQuery queryParams = parseXML(xml);

            filePath = queryParams.getFilePath();
            String applicationName = queryParams.getApplicationName();
            profileId = queryParams.getProfileId();
            String startDate = queryParams.getStartDate();
            String endDate = queryParams.getEndDate();
            List<String> metrics = queryParams.getMetrics();
            List<String> dimensions = queryParams.getDimensions();
            List<String> filters = queryParams.getFilters();
            List<String> sortsCol = queryParams.getSortsCol();
            int maxResults = queryParams.getMaxResults();

            // connect to google analytics
            AnalyticsConnector ac = AnalyticsConnector.getInstance();

            if (setCredentials){
                ac.setCredentials(dataStoreDir, clientSecrets);
            }



            // execute query
            McfData queryResult = ac.executeConversionsQuery(applicationName, profileId, startDate, endDate, metrics, dimensions, filters, sortsCol, maxResults);

            printQueryInfo(queryResult);
            System.out.println();
            printDataTable(queryResult);

            printTotalsForAllResults(queryResult);

            result = resultToXml(queryResult);
            writeXMLFile(filePath, profileId, result);

            System.out.println();
            System.out.println("Result XML:");
            System.out.println(result);


        }catch (GoogleJsonResponseException e) {

            GoogleAnalyticsResult gaResult = new GoogleAnalyticsResult();
            gaResult.HasError = true;

            GoogleJsonError gaError = e.getDetails();

            ErrorsStruct errors  = new ErrorsStruct();
            errors.Message = gaError.getMessage();
            errors.Code = Integer.toString(gaError.getCode());

            List<GoogleJsonError.ErrorInfo> errorInfoCol =  gaError.getErrors();

            errors.Errors = new ArrayList<Error>();

            for(GoogleJsonError.ErrorInfo errorInfo : errorInfoCol){

                Error error = new Error();
                error.Domain = errorInfo.getDomain();
                error.Reason = errorInfo.getReason();
                error.Message = errorInfo.getMessage();
                error.LocationType = errorInfo.getLocationType();
                error.Location = errorInfo.getLocation();

                errors.Errors.add(error);

            }

            gaResult.Errors = errors;

            result = objectToXML(gaResult);
            writeXMLFile(filePath, profileId, result);
            System.err.println(result);

            return result;

        }catch (Exception e){

            GoogleAnalyticsResult gaResult =  new GoogleAnalyticsResult();
            gaResult.HasError = true;

            ErrorsStruct errors  = new ErrorsStruct();
            errors.UnknownError = e.getMessage();

            gaResult.Errors = errors;
            //e.printStackTrace();

            result = objectToXML(gaResult);
            writeXMLFile(filePath, profileId, result);
            System.err.println(result);

            return result;
        }


        return result;
    }

    public String getConversionGoalNumber(String xml){
        String result = "";
        String filePath = "";
        String profileId = "";
        try{
            // Parse xml with Query parameters
            GoogleAnalyticsQuery queryParams = parseXML(xml);

            filePath = queryParams.getFilePath();
            String applicationName = queryParams.getApplicationName();
            profileId = queryParams.getProfileId();
            String startDate = queryParams.getStartDate();
            String endDate = queryParams.getEndDate();
            List<String> metrics = queryParams.getMetrics();
            List<String> dimensions = queryParams.getDimensions();
            List<String> filters = queryParams.getFilters();
            List<String> sortsCol = queryParams.getSortsCol();
            int maxResults = queryParams.getMaxResults();

            // connect to google analytics
            AnalyticsConnector ac = AnalyticsConnector.getInstance();

            if (setCredentials){
                ac.setCredentials(dataStoreDir, clientSecrets);
            }

            // execute query
            McfData queryResult = ac.executeConversionsQuery(applicationName, profileId, startDate, endDate, metrics, dimensions, filters, sortsCol, maxResults);

            printQueryInfo(queryResult);
            System.out.println();
            printDataTable(queryResult);

            printTotalsForAllResults(queryResult);

            result = resultToXml(queryResult);
            writeXMLFile(filePath, profileId, result);

            System.out.println();
            System.out.println("Result XML:");
            System.out.println(result);


        }catch (GoogleJsonResponseException e) {

            GoogleAnalyticsResult gaResult = new GoogleAnalyticsResult();
            gaResult.HasError = true;

            GoogleJsonError gaError = e.getDetails();

            ErrorsStruct errors  = new ErrorsStruct();
            errors.Message = gaError.getMessage();
            errors.Code = Integer.toString(gaError.getCode());

            List<GoogleJsonError.ErrorInfo> errorInfoCol =  gaError.getErrors();

            errors.Errors = new ArrayList<Error>();

            for(GoogleJsonError.ErrorInfo errorInfo : errorInfoCol){

                Error error = new Error();
                error.Domain = errorInfo.getDomain();
                error.Reason = errorInfo.getReason();
                error.Message = errorInfo.getMessage();
                error.LocationType = errorInfo.getLocationType();
                error.Location = errorInfo.getLocation();

                errors.Errors.add(error);

            }

            gaResult.Errors = errors;

            result = objectToXML(gaResult);
            writeXMLFile(filePath, profileId, result);
            System.err.println(result);

            return result;

        }catch (Exception e){

            GoogleAnalyticsResult gaResult =  new GoogleAnalyticsResult();
            gaResult.HasError = true;

            ErrorsStruct errors  = new ErrorsStruct();
            errors.UnknownError = e.getMessage();

            gaResult.Errors = errors;
            //e.printStackTrace();

            result = objectToXML(gaResult);
            writeXMLFile(filePath, profileId, result);
            System.err.println(result);

            return result;
        }


        return result;

    }



    public String getAssistedConversions(String xml){
        //Assisted conversions es: Time on Site > 2 minutes (Goal 2) + Specials Page Views (Goal 4) + Directions Page View (Goal 5)
        String result = "";
        String filePath = "";
        String profileId = "";
        String accountId = "";

        try{

            // Parse xml with Query parameters
            GoogleAnalyticsQuery queryParams = parseXML(xml);

            filePath = queryParams.getFilePath();
            String applicationName = queryParams.getApplicationName();
            profileId = queryParams.getProfileId();
            accountId = queryParams.getAccountId();
            String startDate = queryParams.getStartDate();
            String endDate = queryParams.getEndDate();
            List<String> metrics = queryParams.getMetrics();
            List<String> dimensions = queryParams.getDimensions();
            List<String> filters = queryParams.getFilters();
            List<String> sortsCol = queryParams.getSortsCol();
            int maxResults = queryParams.getMaxResults();


            HashMap<String, String> goalNumbers = getGoalNumbers(accountId, profileId);

            if (goalNumbers.get(Constants.TIME_ON_SITE_GREATER_2_MINUTES.value()) != null){
                metrics.add("ga:goal" + goalNumbers.get(Constants.TIME_ON_SITE_GREATER_2_MINUTES.value()) + "Completions");
            }
            if (goalNumbers.get(Constants.TIME_ON_SITE_GREATER_2_MINUTES_2.value()) != null){
                metrics.add("ga:goal" + goalNumbers.get(Constants.TIME_ON_SITE_GREATER_2_MINUTES_2.value()) + "Completions");
            }
            if (goalNumbers.get(Constants.TIME_ON_SITE_GREATER_2_MIN.value()) != null){
                metrics.add("ga:goal" + goalNumbers.get(Constants.TIME_ON_SITE_GREATER_2_MIN.value()) + "Completions");
            }
            if (goalNumbers.get(Constants.TIME_ON_SITE_GREATER_2.value()) != null){
                metrics.add("ga:goal" + goalNumbers.get(Constants.TIME_ON_SITE_GREATER_2.value()) + "Completions");
            }

            if (goalNumbers.get(Constants.DIRECTIONS_PAGE_VIEW.value()) != null){
                metrics.add("ga:goal" + goalNumbers.get(Constants.DIRECTIONS_PAGE_VIEW.value()) + "Completions");
            }

            if (goalNumbers.get(Constants.DIRECTIONS_PAGE_VIEWS.value()) != null){
                metrics.add("ga:goal" + goalNumbers.get(Constants.DIRECTIONS_PAGE_VIEWS.value()) + "Completions");
            }

            if (goalNumbers.get(Constants.SPECIALS_PAGE_VIEW.value()) != null){
                metrics.add("ga:goal" + goalNumbers.get(Constants.SPECIALS_PAGE_VIEW.value()) + "Completions");
            }

            if (goalNumbers.get(Constants.SPECIALS_PAGE_VIEWS.value()) != null){
                metrics.add("ga:goal" + goalNumbers.get(Constants.SPECIALS_PAGE_VIEWS.value()) + "Completions");
            }




            // connect to google analytics
            AnalyticsConnector ac = AnalyticsConnector.getInstance();

            if (setCredentials){
                ac.setCredentials(dataStoreDir, clientSecrets);
            }



            // execute query
            GaData queryResult = ac.executeQuery(applicationName, profileId, startDate, endDate, metrics, dimensions, filters, sortsCol, maxResults);

            printQueryInfo(queryResult);
            System.out.println();
            printDataTable(queryResult);

            printTotalsForAllResults(queryResult);

            result = resultToXml(queryResult, goalNumbers);
            writeXMLFile(filePath, profileId, result);

            System.out.println();
            System.out.println("Result XML:");
            System.out.println(result);


        }catch (GoogleJsonResponseException e) {

            GoogleAnalyticsResult gaResult = new GoogleAnalyticsResult();
            gaResult.HasError = true;

            GoogleJsonError gaError = e.getDetails();

            ErrorsStruct errors  = new ErrorsStruct();
            errors.Message = gaError.getMessage();
            errors.Code = Integer.toString(gaError.getCode());

            List<GoogleJsonError.ErrorInfo> errorInfoCol =  gaError.getErrors();

            errors.Errors = new ArrayList<Error>();

            for(GoogleJsonError.ErrorInfo errorInfo : errorInfoCol){

                Error error = new Error();
                error.Domain = errorInfo.getDomain();
                error.Reason = errorInfo.getReason();
                error.Message = errorInfo.getMessage();
                error.LocationType = errorInfo.getLocationType();
                error.Location = errorInfo.getLocation();

                errors.Errors.add(error);

            }

            gaResult.Errors = errors;

            result = objectToXML(gaResult);
            writeXMLFile(filePath, profileId, result);
            System.err.println(result);

            return result;

        }catch (Exception e){

            GoogleAnalyticsResult gaResult =  new GoogleAnalyticsResult();
            gaResult.HasError = true;

            ErrorsStruct errors  = new ErrorsStruct();
            errors.UnknownError = e.getMessage();

            gaResult.Errors = errors;
            //e.printStackTrace();

            result = objectToXML(gaResult);
            writeXMLFile(filePath, profileId, result);
            System.err.println(result);

            return result;
        }


        return result;
    }

    public String getSiteEngagementConversions(String xml){
        // Site Engagement Conversion = Lead Submission - General  + Lead Submission - Service  + Specials Page View
        String result = "";
        String filePath = "";
        String profileId = "";
        String accountId = "";

        try{

            // Parse xml with Query parameters
            GoogleAnalyticsQuery queryParams = parseXML(xml);

            filePath = queryParams.getFilePath();
            String applicationName = queryParams.getApplicationName();
            profileId = queryParams.getProfileId();
            accountId = queryParams.getAccountId();
            String startDate = queryParams.getStartDate();
            String endDate = queryParams.getEndDate();
            List<String> metrics = queryParams.getMetrics();
            List<String> dimensions = queryParams.getDimensions();
            List<String> filters = queryParams.getFilters();
            List<String> sortsCol = queryParams.getSortsCol();
            int maxResults = queryParams.getMaxResults();


            HashMap<String, String> goalNumbers = getGoalNumbers(accountId, profileId);

            if (goalNumbers.get(Constants.TIME_ON_SITE_GREATER_2_MINUTES.value()) != null){
                metrics.add("ga:goal" + goalNumbers.get(Constants.TIME_ON_SITE_GREATER_2_MINUTES.value()) + "Completions");
            }
            if (goalNumbers.get(Constants.TIME_ON_SITE_GREATER_2_MINUTES_2.value()) != null){
                metrics.add("ga:goal" + goalNumbers.get(Constants.TIME_ON_SITE_GREATER_2_MINUTES_2.value()) + "Completions");
            }
            if (goalNumbers.get(Constants.TIME_ON_SITE_GREATER_2_MIN.value()) != null){
                metrics.add("ga:goal" + goalNumbers.get(Constants.TIME_ON_SITE_GREATER_2_MIN.value()) + "Completions");
            }
            if (goalNumbers.get(Constants.TIME_ON_SITE_GREATER_2.value()) != null){
                metrics.add("ga:goal" + goalNumbers.get(Constants.TIME_ON_SITE_GREATER_2.value()) + "Completions");
            }

            if (goalNumbers.get(Constants.DIRECTIONS_PAGE_VIEW.value()) != null){
                metrics.add("ga:goal" + goalNumbers.get(Constants.DIRECTIONS_PAGE_VIEW.value()) + "Completions");
            }

            if (goalNumbers.get(Constants.DIRECTIONS_PAGE_VIEWS.value()) != null){
                metrics.add("ga:goal" + goalNumbers.get(Constants.DIRECTIONS_PAGE_VIEWS.value()) + "Completions");
            }

            if (goalNumbers.get(Constants.SPECIALS_PAGE_VIEW.value()) != null){
                metrics.add("ga:goal" + goalNumbers.get(Constants.SPECIALS_PAGE_VIEW.value()) + "Completions");
            }

            if (goalNumbers.get(Constants.SPECIALS_PAGE_VIEWS.value()) != null){
                metrics.add("ga:goal" + goalNumbers.get(Constants.SPECIALS_PAGE_VIEWS.value()) + "Completions");
            }

            // connect to google analytics
            AnalyticsConnector ac = AnalyticsConnector.getInstance();

            if (setCredentials){
                ac.setCredentials(dataStoreDir, clientSecrets);
            }



            // execute query
            GaData queryResult = ac.executeQuery(applicationName, profileId, startDate, endDate, metrics, dimensions, filters, sortsCol, maxResults);

            printQueryInfo(queryResult);
            System.out.println();
            printDataTable(queryResult);

            printTotalsForAllResults(queryResult);

            result = resultToXml(queryResult, goalNumbers);
            writeXMLFile(filePath, profileId, result);

            System.out.println();
            System.out.println("Result XML:");
            System.out.println(result);


        }catch (GoogleJsonResponseException e) {

            GoogleAnalyticsResult gaResult = new GoogleAnalyticsResult();
            gaResult.HasError = true;

            GoogleJsonError gaError = e.getDetails();

            ErrorsStruct errors  = new ErrorsStruct();
            errors.Message = gaError.getMessage();
            errors.Code = Integer.toString(gaError.getCode());

            List<GoogleJsonError.ErrorInfo> errorInfoCol =  gaError.getErrors();

            errors.Errors = new ArrayList<Error>();

            for(GoogleJsonError.ErrorInfo errorInfo : errorInfoCol){

                Error error = new Error();
                error.Domain = errorInfo.getDomain();
                error.Reason = errorInfo.getReason();
                error.Message = errorInfo.getMessage();
                error.LocationType = errorInfo.getLocationType();
                error.Location = errorInfo.getLocation();

                errors.Errors.add(error);

            }

            gaResult.Errors = errors;

            result = objectToXML(gaResult);
            writeXMLFile(filePath, profileId, result);
            System.err.println(result);

            return result;

        }catch (Exception e){

            GoogleAnalyticsResult gaResult =  new GoogleAnalyticsResult();
            gaResult.HasError = true;

            ErrorsStruct errors  = new ErrorsStruct();
            errors.UnknownError = e.getMessage();

            gaResult.Errors = errors;
            //e.printStackTrace();

            result = objectToXML(gaResult);
            writeXMLFile(filePath, profileId, result);
            System.err.println(result);

            return result;
        }


        return result;
    }

    public String getInventoryPageViews(String xml){

        String result = "";
        String filePath = "";
        String profileId = "";
        String accountId = "";

        try{

            // Parse xml with Query parameters
            GoogleAnalyticsQuery queryParams = parseXML(xml);

            filePath = queryParams.getFilePath();
            String applicationName = queryParams.getApplicationName();
            profileId = queryParams.getProfileId();
            accountId = queryParams.getAccountId();
            String startDate = queryParams.getStartDate();
            String endDate = queryParams.getEndDate();
            List<String> metrics = queryParams.getMetrics();
            List<String> dimensions = queryParams.getDimensions();
            List<String> filters = queryParams.getFilters();
            List<String> sortsCol = queryParams.getSortsCol();
            int maxResults = queryParams.getMaxResults();


            HashMap<String, String> goalNumbers = getGoalNumbers(accountId, profileId);

            if (goalNumbers.get(Constants.INVENTORY_PAGE_VIEW.value()) != null){

                metrics.add("ga:goal" + goalNumbers.get(Constants.INVENTORY_PAGE_VIEW.value()) + "Completions");
            }else{
                metrics.add("ga:goal" + goalNumbers.get(Constants.INVENTORY_PAGE_VIEWS.value()) + "Completions");
            }


            // connect to google analytics
            AnalyticsConnector ac = AnalyticsConnector.getInstance();

            if (setCredentials){
                ac.setCredentials(dataStoreDir, clientSecrets);
            }



            // execute query
            GaData queryResult = ac.executeQuery(applicationName, profileId, startDate, endDate, metrics, dimensions, filters, sortsCol, maxResults);

            printQueryInfo(queryResult);
            System.out.println();
            printDataTable(queryResult);

            printTotalsForAllResults(queryResult);

            result = resultToXml(queryResult, goalNumbers);
            writeXMLFile(filePath, profileId, result);

            System.out.println();
            System.out.println("Result XML:");
            System.out.println(result);


        }catch (GoogleJsonResponseException e) {

            GoogleAnalyticsResult gaResult = new GoogleAnalyticsResult();
            gaResult.HasError = true;

            GoogleJsonError gaError = e.getDetails();

            ErrorsStruct errors  = new ErrorsStruct();
            errors.Message = gaError.getMessage();
            errors.Code = Integer.toString(gaError.getCode());

            List<GoogleJsonError.ErrorInfo> errorInfoCol =  gaError.getErrors();

            errors.Errors = new ArrayList<Error>();

            for(GoogleJsonError.ErrorInfo errorInfo : errorInfoCol){

                Error error = new Error();
                error.Domain = errorInfo.getDomain();
                error.Reason = errorInfo.getReason();
                error.Message = errorInfo.getMessage();
                error.LocationType = errorInfo.getLocationType();
                error.Location = errorInfo.getLocation();

                errors.Errors.add(error);

            }

            gaResult.Errors = errors;

            result = objectToXML(gaResult);
            writeXMLFile(filePath, profileId, result);
            System.err.println(result);

            return result;

        }catch (Exception e){

            GoogleAnalyticsResult gaResult =  new GoogleAnalyticsResult();
            gaResult.HasError = true;

            ErrorsStruct errors  = new ErrorsStruct();
            errors.UnknownError = e.getMessage();

            gaResult.Errors = errors;
            //e.printStackTrace();

            result = objectToXML(gaResult);
            writeXMLFile(filePath, profileId, result);
            System.err.println(result);

            return result;
        }


        return result;

    }

    public String getUsersAndSessions(String xml){



        String result = "";
        String filePath = "";
        String profileId = "";
        String accountId = "";

        try{
            // Parse xml with Query parameters
            GoogleAnalyticsQuery queryParams = parseXML(xml);

            filePath = queryParams.getFilePath();
            String applicationName = queryParams.getApplicationName();
            profileId = queryParams.getProfileId();
            accountId = queryParams.getAccountId();
            String startDate = queryParams.getStartDate();
            String endDate = queryParams.getEndDate();
            List<String> metrics = queryParams.getMetrics();
            List<String> dimensions = queryParams.getDimensions();
            List<String> filters = queryParams.getFilters();
            List<String> sortsCol = queryParams.getSortsCol();
            int maxResults = queryParams.getMaxResults();

            // connect to google analytics
            AnalyticsConnector ac = AnalyticsConnector.getInstance();

            if (setCredentials){
                ac.setCredentials(dataStoreDir, clientSecrets);
            }


            // execute query
            GaData queryResult = null;
            try{
             queryResult = ac.executeQuery(applicationName, profileId, startDate, endDate, metrics, dimensions, filters, sortsCol, maxResults);

            }catch (Exception exe){



            }
            printQueryInfo(queryResult);
            System.out.println();
            printDataTable(queryResult);

            printTotalsForAllResults(queryResult);

            result = resultToXml(queryResult);
            writeXMLFile(filePath, profileId, result);

            System.out.println();
            System.out.println("Result XML:");
            System.out.println(result);


        }catch (GoogleJsonResponseException e) {
            GoogleAnalyticsResult gaResult = new GoogleAnalyticsResult();
            gaResult.HasError = true;

            GoogleJsonError gaError = e.getDetails();

            ErrorsStruct errors  = new ErrorsStruct();
            errors.Message = gaError.getMessage();
            errors.Code = Integer.toString(gaError.getCode());

            List<GoogleJsonError.ErrorInfo> errorInfoCol =  gaError.getErrors();

            errors.Errors = new ArrayList<Error>();

            for(GoogleJsonError.ErrorInfo errorInfo : errorInfoCol){

                Error error = new Error();
                error.Domain = errorInfo.getDomain();
                error.Reason = errorInfo.getReason();
                error.Message = errorInfo.getMessage();
                error.LocationType = errorInfo.getLocationType();
                error.Location = errorInfo.getLocation();

                errors.Errors.add(error);

            }

            gaResult.Errors = errors;

            result = objectToXML(gaResult);
            writeXMLFile(filePath, profileId, result);
            System.err.println(result);



            return result;

        }catch (Exception e){
            GoogleAnalyticsResult gaResult =  new GoogleAnalyticsResult();
            gaResult.HasError = true;

            ErrorsStruct errors  = new ErrorsStruct();
            errors.UnknownError = e.getMessage();

            gaResult.Errors = errors;
            //e.printStackTrace();

            StringWriter err = new StringWriter();
            e.printStackTrace(new PrintWriter(err));

            result = objectToXML(gaResult);
            writeXMLFile(filePath, profileId, result);
            System.err.println(result);




            return result;
        }


        return result;


    }

    public HashMap<String, String> getGoalNumbers(String accountId, String profileId){
        HashMap<String, String> result = new HashMap<String, String>();
        try{
            AnalyticsConnector connector = new AnalyticsConnector();

            if (setCredentials){
                connector.setCredentials(dataStoreDir, clientSecrets);
            }

            Analytics analytics = connector.initializeAnalytics();
            Goals goals = analytics.management().goals().list(accountId, "~all", "~all").execute();
            for(Goal goal : goals.getItems()){

                if (goal.getProfileId().equalsIgnoreCase(profileId)){
                    if (goal.getName().trim().equalsIgnoreCase(Constants.INVENTORY_PAGE_VIEW.value())){
                        result.put(Constants.INVENTORY_PAGE_VIEW.value(), goal.getId());
                    }
                    if (goal.getName().trim().equalsIgnoreCase(Constants.INVENTORY_PAGE_VIEWS.value())){
                        result.put(Constants.INVENTORY_PAGE_VIEWS.value(), goal.getId());
                    }
                    if (goal.getName().trim().equalsIgnoreCase(Constants.LEAD_SUBMISSION_GENERAL.value())){
                        result.put(Constants.LEAD_SUBMISSION_GENERAL.value(), goal.getId());
                    }
                    if (goal.getName().trim().equalsIgnoreCase(Constants.LEAD_SUBMISSION_SERVICE.value())){
                        result.put(Constants.LEAD_SUBMISSION_SERVICE.value(), goal.getId());
                    }
                    if (goal.getName().trim().equalsIgnoreCase(Constants.DIRECTIONS_PAGE_VIEW.value())){
                        result.put(Constants.DIRECTIONS_PAGE_VIEW.value(), goal.getId());
                    }
                    if (goal.getName().trim().equalsIgnoreCase(Constants.DIRECTIONS_PAGE_VIEWS.value())){
                        result.put(Constants.DIRECTIONS_PAGE_VIEWS.value(), goal.getId());
                    }
                    if (goal.getName().trim().equalsIgnoreCase(Constants.SPECIALS_PAGE_VIEW.value())){
                        result.put(Constants.SPECIALS_PAGE_VIEW.value(), goal.getId());
                    }
                    if (goal.getName().trim().equalsIgnoreCase(Constants.SPECIALS_PAGE_VIEWS.value())){
                        result.put(Constants.SPECIALS_PAGE_VIEWS.value(), goal.getId());
                    }
                    if (goal.getName().trim().equalsIgnoreCase(Constants.TIME_ON_SITE_GREATER_2_MINUTES.value())){
                        result.put(Constants.TIME_ON_SITE_GREATER_2_MINUTES.value(), goal.getId());
                    }
                    if (goal.getName().trim().equalsIgnoreCase(Constants.TIME_ON_SITE_GREATER_2_MINUTES_2.value())){
                        result.put(Constants.TIME_ON_SITE_GREATER_2_MINUTES_2.value(), goal.getId());
                    }
                    if (goal.getName().trim().equalsIgnoreCase(Constants.TIME_ON_SITE_GREATER_2.value())){
                        result.put(Constants.TIME_ON_SITE_GREATER_2.value(), goal.getId());
                    }
                    if (goal.getName().trim().equalsIgnoreCase(Constants.TIME_ON_SITE_GREATER_2_MIN.value())){
                        result.put(Constants.TIME_ON_SITE_GREATER_2_MIN.value(), goal.getId());
                    }
                }

            }

        } catch (IOException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        } catch (Exception e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }
        return result;
    }

    public String getAccounts(String xml){
        try {
            AnalyticsConnector ac = new AnalyticsConnector();
            if (setCredentials){
                ac.setCredentials(dataStoreDir, clientSecrets);
            }

            Analytics connector = ac.initializeAnalytics();



            Accounts accounts = connector.management().accounts().list().execute();

            for (Account account:accounts.getItems()){

                System.out.println("Account id: " + account.getId());
                System.out.println("Account name: " + account.getName());
                System.out.println("Account kind: " + account.getKind());

                System.out.println(getProfiles(account.getId()));

                System.out.println("=========================================================================");



            }

        } catch (Exception e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }
        return "";
    }

    public String getProfiles(String accountId){
        String result = "";
        try {
            AnalyticsConnector ac = new AnalyticsConnector();
            if (setCredentials){
                ac.setCredentials(dataStoreDir, clientSecrets);
            }

            Analytics connector = ac.initializeAnalytics();




            Profiles profiles = connector.management().profiles().list(accountId, "~all").execute();

            for (Profile profile : profiles.getItems()){
                result += profile.getId() + ";";

            }

        } catch (Exception e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }
        return result;
    }

    private GoogleAnalyticsQuery parseXML(String xml) throws Exception{


        GoogleAnalyticsQuery queryParams = new GoogleAnalyticsQuery();

        Util util = new Util();

        Document doc = util.loadXMLFromString(xml);

        XPathFactory factory = XPathFactory.newInstance();
        XPath xpath = factory.newXPath();

        XPathExpression expr
                = xpath.compile("//GoogleAnalyticsQuery");

        Object queriesNodes = expr.evaluate(doc, XPathConstants.NODESET);

        NodeList queries = (NodeList) queriesNodes;

        if (queries.getLength() > 0) {

            for (int i = 0; i < queries.getLength(); i++) { // For all Query Nodes

                Node n = queries.item(i);

                NodeList children = n.getChildNodes();

                if (children.getLength() > 0) {

                    for (int j = 0; j < children.getLength(); j++) {

                        // filePath
                        if (children.item(j).getNodeName().equalsIgnoreCase(Constants.FILE_PATH.value())) {
                            queryParams.setFilePath(children.item(j).getTextContent());
                        }

                        // applicationName
                        if (children.item(j).getNodeName().equalsIgnoreCase(Constants.APPLICATION_NAME.value())) {
                            queryParams.setApplicationName(children.item(j).getTextContent());
                        }

                        // profileId
                        if (children.item(j).getNodeName().equalsIgnoreCase(Constants.PROFILE_ID.value())) {
                            queryParams.setProfileId(children.item(j).getTextContent());
                        }

                        // accountId
                        if (children.item(j).getNodeName().equalsIgnoreCase(Constants.ACCOUNT_ID.value())) {
                            queryParams.setAccountId(children.item(j).getTextContent());
                        }

                        // query
                        if (children.item(j).getNodeName().equalsIgnoreCase(Constants.QUERY.value())){
                            queryParams.setQuery(children.item(j).getTextContent());
                        }

                        // analyticsImportId
                        if (children.item(j).getNodeName().equalsIgnoreCase(Constants.ANALYTICS_IMPORT_ID.value())){
                            queryParams.setAnalyticsImportId(Long.parseLong(children.item(j).getTextContent()));
                        }

                        // startDate
                        if (children.item(j).getNodeName().equalsIgnoreCase(Constants.START_DATE.value())) {
                            queryParams.setStartDate(children.item(j).getTextContent());
                        }

                        // endDate
                        if (children.item(j).getNodeName().equalsIgnoreCase(Constants.END_DATE.value())) {
                            queryParams.setEndDate(children.item(j).getTextContent());
                        }

                        // metrics
                        if (children.item(j).getNodeName().equalsIgnoreCase(Constants.METRICS.value())) {
                            NodeList metricsNodes = children.item(j).getChildNodes();
                            queryParams.setMetrics(getParamsListFromNodes(metricsNodes));
                        }

                        // dimensions
                        if (children.item(j).getNodeName().equalsIgnoreCase(Constants.DIMENSIONS.value())) {
                            NodeList metricsNodes = children.item(j).getChildNodes();
                            queryParams.setDimensions(getParamsListFromNodes(metricsNodes));
                        }

                        // filters
                        if (children.item(j).getNodeName().equalsIgnoreCase(Constants.FILTERS.value())) {
                            NodeList filtersNodes = children.item(j).getChildNodes();
                            queryParams.setFilters(getParamsListFromNodes(filtersNodes));
                        }

                        // sorts
                        if (children.item(j).getNodeName().equalsIgnoreCase(Constants.SORTS.value())) {
                            NodeList metricsNodes = children.item(j).getChildNodes();
                            queryParams.setSortsCol(getParamsListFromNodes(metricsNodes));
                        }

                        // maxResults
                        if (children.item(j).getNodeName().equalsIgnoreCase(Constants.MAX_RESULTS.value())) {
                            queryParams.setMaxResults(Integer.parseInt(children.item(j).getTextContent()));
                        }

                    }

                }

            }
        }

        return queryParams ;
    }

    /**
     * Creates a comma separated string from a list of nodes
     *
     * @param nodeList
     * @return
     * @throws Exception
     */
    private List<String> getParamsListFromNodes(NodeList nodeList) throws Exception{
        if (nodeList.getLength() == 0) return null;
        List<String> params = new ArrayList<String>();

        for (int j = 0; j < nodeList.getLength(); j++) {

            String param = nodeList.item(j).getTextContent();
            if (param.trim().length() > 0)
                params.add(param);
        }
        return params;
    }

    private String resultToXml(GaData resultData) throws Exception{

        GoogleAnalyticsResult gaResult = new GoogleAnalyticsResult();

        Map<String, String> totals = resultData.getTotalsForAllResults();

        for (Map.Entry<String,String> entry : totals.entrySet()) {

            String metric = entry.getKey();
            String value = entry.getValue();

            if (metric.equals(Constants.VISITS.value())){
                gaResult.TotalVisits =  Float.parseFloat(value);
            }

            if (metric.equals(Constants.NEW_VISITS.value())){
                gaResult.NewVisits =  Float.parseFloat(value);
            }

            if (metric.equals(Constants.UNIQUE_VISITORS.value())){
                gaResult.TotalUniqueVisits =  Float.parseFloat(value);
            }

            if (metric.equals(Constants.PAGE_VIEWS.value())){
                gaResult.TotalPageviews =  Float.parseFloat(value);
            }

            if (metric.equals(Constants.PAGES_PER_VISIT.value())){
                gaResult.PagesPerVisit =  Float.parseFloat(value);
            }

            if (metric.equals(Constants.VISIT_DURATION.value())){
                gaResult.TimeOnSite =  Float.parseFloat(value);
            }

            if (metric.equals(Constants.AVG_VISIT_DURATION.value())){
                gaResult.AvgVisitDuration =  Float.parseFloat(value);
            }

            if (metric.equals(Constants.BOUNCE_RATE.value())){
                gaResult.BounceRate =  Float.parseFloat(value);
            }

            if (metric.equals(Constants.BOUNCES.value())){
                gaResult.Bounces = Float.parseFloat(value);
            }

            if (metric.equals(Constants.NEW_VISITS_PERCENTAGE.value())){
                gaResult.NewVisitsPercentage =  Float.parseFloat(value);
            }

            if (metric.equals(Constants.NON_BRANDED_VISITS.value())){
                gaResult.TotalNonBrandedVisits =  Float.parseFloat(value);
            }

            if (metric.equals(Constants.ASSISTED_CONVERSIONS.value())){
                List<GaData.ColumnHeaders> chs = resultData.getColumnHeaders();
                for (int i = 0; i < chs.size(); i++){
                    GaData.ColumnHeaders ch = chs.get(i);
                    if (ch.getName().equalsIgnoreCase(metric)){
                        List<List<String>> rows = resultData.getRows();
                        gaResult.AssistedConversions = new ArrayList<AssistedConversion>();
                        for (List<String> row : rows){
                            AssistedConversion ac = new AssistedConversion();
                            ac.AdwordsCampaignId = row.get(0);
                            ac.Value = row.get(i);
                            gaResult.AssistedConversions.add(ac);
                        }
                    }
                }
            }

            if (metric.equalsIgnoreCase(Constants.NEW_USERS.value())){
                gaResult.Users = Integer.parseInt(value);
            }

            if (metric.equalsIgnoreCase(Constants.SESSIONS.value())){
                gaResult.Sessions = Integer.parseInt(value);
            }

            if (metric.equalsIgnoreCase(Constants.LEAD_SUBMISSION_GENERAL.value())){
                gaResult.LeadSubmissionsGeneral = Integer.parseInt(value);
            }

            if (metric.equalsIgnoreCase(Constants.LEAD_SUBMISSION_SERVICE.value())){
                gaResult.LeadSubmissionsService = Integer.parseInt(value);
            }

            if (metric.equalsIgnoreCase(Constants.SPECIALS_PAGE_VIEW.value())){
               // gaResult.SpecialPageViews = Integer.parseInt(value);
            }

            if (metric.equalsIgnoreCase(Constants.INVENTORY_PAGE_VIEWS.value()) ||
                    metric.equalsIgnoreCase(Constants.INVENTORY_PAGE_VIEW.value())){
                //gaResult.PageInventoryViews = Long.parseLong(value);
                List<List<String>> rows = resultData.getRows();
                gaResult.PageInventoryViews = new ArrayList<PageInventoryView>();
                for (List<String> row : rows){
                    PageInventoryView piv = new PageInventoryView();
                    piv.AdwordsCampaignId = row.get(0);
                    piv.Value = row.get(1);
                    gaResult.PageInventoryViews.add(piv);
                }
            }

            System.out.println(entry.getKey() + " : " + entry.getValue());

        }

        return objectToXML(gaResult);

        /*
        if (resultData.getTotalResults() > 0) {

            // Load the column names.
            for (GaData.ColumnHeaders header : resultData.getColumnHeaders()) {
                GoogleAnalyticsResultItem gaResultItem = new GoogleAnalyticsResultItem();
                gaResultItem.value = header.getName();
                gaResult.columns.add(gaResultItem);
            }

            // Load the rows of data.
            for (List<String> rowValues : resultData.getRows()) {
                for (String value : rowValues) {
                    GoogleAnalyticsResultItem gaResultItem = new GoogleAnalyticsResultItem();
                    gaResultItem.value = value;
                    gaResult.rows.add(gaResultItem);
                }

            }
        } else {

            ErrorsStruct errors =  new ErrorsStruct();
            gaResult.HasError = true;
            errors.UnknownError = "Query returned no data from Google Analytics";

            gaResult.Errors = errors;

        }
        */

    }

    private String resultToXml(GaData resultData, HashMap<String, String> goalNumbers) throws Exception{

        GoogleAnalyticsResult gaResult = new GoogleAnalyticsResult();

        Map<String, String> totals = resultData.getTotalsForAllResults();

        for (Map.Entry<String,String> entry : totals.entrySet()) {

            String metric = entry.getKey();
            String value = entry.getValue();

            if (metric.equals(Constants.VISITS.value())){
                gaResult.TotalVisits =  Float.parseFloat(value);
            }

            if (metric.equals(Constants.NEW_VISITS.value())){
                gaResult.NewVisits =  Float.parseFloat(value);
            }

            if (metric.equals(Constants.UNIQUE_VISITORS.value())){
                gaResult.TotalUniqueVisits =  Float.parseFloat(value);
            }

            if (metric.equals(Constants.PAGE_VIEWS.value())){
                gaResult.TotalPageviews =  Float.parseFloat(value);
            }

            if (metric.equals(Constants.PAGES_PER_VISIT.value())){
                gaResult.PagesPerVisit =  Float.parseFloat(value);
            }

            if (metric.equals(Constants.VISIT_DURATION.value())){
                gaResult.TimeOnSite =  Float.parseFloat(value);
            }

            if (metric.equals(Constants.AVG_VISIT_DURATION.value())){
                gaResult.AvgVisitDuration =  Float.parseFloat(value);
            }

            if (metric.equals(Constants.BOUNCE_RATE.value())){
                gaResult.BounceRate =  Float.parseFloat(value);
            }

            if (metric.equals(Constants.BOUNCES.value())){
                gaResult.Bounces = Float.parseFloat(value);
            }

            if (metric.equals(Constants.NEW_VISITS_PERCENTAGE.value())){
                gaResult.NewVisitsPercentage =  Float.parseFloat(value);
            }

            if (metric.equals(Constants.NON_BRANDED_VISITS.value())){
                gaResult.TotalNonBrandedVisits =  Float.parseFloat(value);
            }

            if (metric.equals(Constants.ASSISTED_CONVERSIONS.value())){
                List<GaData.ColumnHeaders> chs = resultData.getColumnHeaders();
                for (int i = 0; i < chs.size(); i++){
                    GaData.ColumnHeaders ch = chs.get(i);
                    if (ch.getName().equalsIgnoreCase(metric)){
                        List<List<String>> rows = resultData.getRows();
                        gaResult.AssistedConversions = new ArrayList<AssistedConversion>();
                        for (List<String> row : rows){
                            AssistedConversion ac = new AssistedConversion();
                            ac.AdwordsCampaignId = row.get(0);
                            ac.Value = row.get(i);
                            gaResult.AssistedConversions.add(ac);
                        }
                    }
                }
            }

            if (metric.equalsIgnoreCase(Constants.NEW_USERS.value())){
                gaResult.Users = Integer.parseInt(value);
            }

            if (metric.equalsIgnoreCase(Constants.NEW_USERS.value())){
                gaResult.Users = Integer.parseInt(value);
            }

            if (metric.equalsIgnoreCase("ga:goal" + goalNumbers.get(Constants.LEAD_SUBMISSION_GENERAL.value()) + "Completions")){
                gaResult.LeadSubmissionsGeneral = Integer.parseInt(value);
            }

            if (metric.equalsIgnoreCase("ga:goal" + goalNumbers.get(Constants.LEAD_SUBMISSION_SERVICE.value()) + "Completions")){
                gaResult.LeadSubmissionsService = Integer.parseInt(value);
            }

            if (metric.equalsIgnoreCase("ga:goal" + goalNumbers.get(Constants.SPECIALS_PAGE_VIEW.value()) + "Completions") ||
                    metric.equalsIgnoreCase("ga:goal" + goalNumbers.get(Constants.SPECIALS_PAGE_VIEWS.value()) + "Completions")){
                //gaResult.SpecialPageViews = Integer.parseInt(value);

                List<GaData.ColumnHeaders> chs = resultData.getColumnHeaders();

                for (int i = 0; i < chs.size(); i++){
                    GaData.ColumnHeaders ch = chs.get(i);
                    if (ch.getName().equalsIgnoreCase(metric)){
                        List<List<String>> rows = resultData.getRows();
                        gaResult.SpecialPageViews = new ArrayList<Special>();
                        for (List<String> row : rows){
                            Special s = new Special();
                            s.AdwordsCampaignId = row.get(0);
                            s.Value = row.get(i);
                            gaResult.SpecialPageViews.add(s);
                        }
                    }
                }
            }

            if (metric.equalsIgnoreCase("ga:goal" + goalNumbers.get(Constants.DIRECTIONS_PAGE_VIEW.value()) + "Completions") ||
                metric.equalsIgnoreCase("ga:goal" + goalNumbers.get(Constants.DIRECTIONS_PAGE_VIEWS.value()) + "Completions")){
                //gaResult.DirectionPageViews = Integer.parseInt(value);
                List<GaData.ColumnHeaders> chs = resultData.getColumnHeaders();

                for (int i = 0; i < chs.size(); i++){
                    GaData.ColumnHeaders ch = chs.get(i);
                    if (ch.getName().equalsIgnoreCase(metric)){
                        List<List<String>> rows = resultData.getRows();
                        gaResult.DirectionPageViews = new ArrayList<Direction>();
                        for (List<String> row : rows){
                            Direction d = new Direction();
                            d.AdwordsCampaignId = row.get(0);
                            d.Value = row.get(i);
                            gaResult.DirectionPageViews.add(d);
                        }
                    }
                }
            }

            if (metric.equalsIgnoreCase("ga:goal" + goalNumbers.get(Constants.TIME_ON_SITE_GREATER_2_MINUTES.value()) + "Completions") ||
                    metric.equalsIgnoreCase("ga:goal" + goalNumbers.get(Constants.TIME_ON_SITE_GREATER_2.value()) + "Completions") ||
                    metric.equalsIgnoreCase("ga:goal" + goalNumbers.get(Constants.TIME_ON_SITE_GREATER_2_MIN.value()) + "Completions") ||
                    metric.equalsIgnoreCase("ga:goal" + goalNumbers.get(Constants.TIME_ON_SITE_GREATER_2_MINUTES_2.value()) + "Completions")){
                //gaResult.TimeGreater2Minutes = Integer.parseInt(value);
                List<GaData.ColumnHeaders> chs = resultData.getColumnHeaders();

                for (int i = 0; i < chs.size(); i++){
                    GaData.ColumnHeaders ch = chs.get(i);
                    if (ch.getName().equalsIgnoreCase(metric)){
                        List<List<String>> rows = resultData.getRows();
                        gaResult.Times = new ArrayList<TimeOnSite>();
                        for (List<String> row : rows){
                            TimeOnSite t = new TimeOnSite();
                            t.AdwordsCampaignId = row.get(0);
                            t.Value = row.get(i);
                            gaResult.Times.add(t);
                        }
                    }
                }
            }

            if (metric.equalsIgnoreCase("ga:goal" + goalNumbers.get(Constants.INVENTORY_PAGE_VIEW.value()) + "Completions") ||
                    metric.equalsIgnoreCase("ga:goal" + goalNumbers.get(Constants.INVENTORY_PAGE_VIEWS.value()) + "Completions")){
                //gaResult.PageInventoryViews = Long.parseLong(value);
                List<List<String>> rows = resultData.getRows();
                gaResult.PageInventoryViews = new ArrayList<PageInventoryView>();
                for (List<String> row : rows){
                    PageInventoryView piv = new PageInventoryView();
                    piv.AdwordsCampaignId = row.get(0);
                    piv.Value = row.get(1);
                    gaResult.PageInventoryViews.add(piv);
                }
            }

            System.out.println(entry.getKey() + " : " + entry.getValue());

        }

        //gaResult.SiteEngagementConversions = gaResult.TimeGreater2Minutes + gaResult.SpecialPageViews + gaResult.DirectionPageViews;
        //gaResult.AssistedConversions = gaResult.TimeGreater2Minutes + gaResult.SpecialPageViews + gaResult.DirectionPageViews;

        return objectToXML(gaResult);

        /*
        if (resultData.getTotalResults() > 0) {

            // Load the column names.
            for (GaData.ColumnHeaders header : resultData.getColumnHeaders()) {
                GoogleAnalyticsResultItem gaResultItem = new GoogleAnalyticsResultItem();
                gaResultItem.value = header.getName();
                gaResult.columns.add(gaResultItem);
            }

            // Load the rows of data.
            for (List<String> rowValues : resultData.getRows()) {
                for (String value : rowValues) {
                    GoogleAnalyticsResultItem gaResultItem = new GoogleAnalyticsResultItem();
                    gaResultItem.value = value;
                    gaResult.rows.add(gaResultItem);
                }

            }
        } else {

            ErrorsStruct errors =  new ErrorsStruct();
            gaResult.HasError = true;
            errors.UnknownError = "Query returned no data from Google Analytics";

            gaResult.Errors = errors;

        }
        */

    }

    private String resultToXml(McfData resultData) throws Exception{

        GoogleAnalyticsResult gaResult = new GoogleAnalyticsResult();

        Map<String, String> totals = resultData.getTotalsForAllResults();

        for (Map.Entry<String,String> entry : totals.entrySet()) {

            String metric = entry.getKey();
            String value = entry.getValue();

            if (metric.equals(Constants.VISITS.value())){
                gaResult.TotalVisits =  Float.parseFloat(value);
            }

            if (metric.equals(Constants.NEW_VISITS.value())){
                gaResult.NewVisits =  Float.parseFloat(value);
            }

            if (metric.equals(Constants.UNIQUE_VISITORS.value())){
                gaResult.TotalUniqueVisits =  Float.parseFloat(value);
            }

            if (metric.equals(Constants.PAGE_VIEWS.value())){
                gaResult.TotalPageviews =  Float.parseFloat(value);
            }

            if (metric.equals(Constants.PAGES_PER_VISIT.value())){
                gaResult.PagesPerVisit =  Float.parseFloat(value);
            }


            if (metric.equals(Constants.VISIT_DURATION.value())){
                gaResult.TimeOnSite =  Float.parseFloat(value);
            }

            if (metric.equals(Constants.AVG_VISIT_DURATION.value())){
                gaResult.AvgVisitDuration =  Float.parseFloat(value);
            }

            if (metric.equals(Constants.BOUNCE_RATE.value())){
                gaResult.BounceRate = Float.parseFloat(value);
            }

            if (metric.equals(Constants.BOUNCES.value())){
                gaResult.Bounces = Float.parseFloat(value);
            }

            if (metric.equals(Constants.NEW_VISITS_PERCENTAGE.value())){
                gaResult.NewVisitsPercentage =  Float.parseFloat(value);
            }

            if (metric.equals(Constants.NON_BRANDED_VISITS.value())){
                gaResult.TotalNonBrandedVisits =  Float.parseFloat(value);
            }

            if (metric.equals(Constants.ASSISTED_CONVERSIONS.value())){
                List<McfData.ColumnHeaders> chs = resultData.getColumnHeaders();
                for (int i = 0; i < chs.size(); i++){
                    McfData.ColumnHeaders ch = chs.get(i);
                    if (ch.getName().equalsIgnoreCase(metric)){
                        List<List<McfData.Rows>> rows = resultData.getRows();
                        gaResult.AssistedConversions = new ArrayList<AssistedConversion>();
                        for (List<McfData.Rows> row : rows){
                            AssistedConversion ac = new AssistedConversion();
                            ac.ConversionType = row.get(0).getPrimitiveValue();
                            ac.AdwordsCampaignId = row.get(1).getPrimitiveValue();
                            ac.Value = row.get(2).getPrimitiveValue();
                            gaResult.AssistedConversions.add(ac);
                        }
                    }
                }
            }

            System.out.println(entry.getKey() + " : " + entry.getValue());

        }

        return objectToXML(gaResult);
    }

    private String top10resultToXML(GaData resultData) throws Exception{

        Top10KeywordsResult gaResult = new Top10KeywordsResult();

        if (resultData.getTotalResults() > 0) {

            // Load the rows of data.
            Object[] columns = resultData.getColumnHeaders().toArray();

            for (List<String> row : resultData.getRows()) {
                Top10KeywordsResultItem gaResultItem = new Top10KeywordsResultItem();
                Object[] rowValues = row.toArray();
                if (rowValues.length == columns.length) {
                    for (int i=0; i<rowValues.length; i++) {
                        String value = (String)rowValues[i];
                        String column = ((GaData.ColumnHeaders)columns[i]).getName();

                        if (column.equals(Constants.KEYWORD.value()) || column.equals(Constants.EVENT_LABEL.value())){
                            gaResultItem.Keyword = value;
                        } else
                        if (column.equals(Constants.VISITS.value())){
                            gaResultItem.TotalVisits = Float.parseFloat(value);
                        } else
                        if (column.equals(Constants.UNIQUE_VISITORS.value())){
                            gaResultItem.TotalUniqueVisitors = Float.parseFloat(value);
                        } else
                        if (column.equals(Constants.PAGE_VIEWS.value())){
                            gaResultItem.TotalPageviews = Float.parseFloat(value);
                        } else
                        if (column.equals(Constants.VISIT_DURATION.value())){
                            gaResultItem.TimeOnSite = Float.parseFloat(value);
                        } else
                        if (column.equals(Constants.NEW_VISITS.value())){
                            gaResultItem.NewVisits = Float.parseFloat(value);
                        } else
                        if (column.equals(Constants.BOUNCES.value())){
                            gaResultItem.Bounces = Float.parseFloat(value);
                        } else {
                            gaResultItem.Value = Float.parseFloat(value);
                        }
                    }
                    gaResult.Results.add(gaResultItem);
                }
            }
        } else {

            ErrorsStruct errors =  new ErrorsStruct();
            gaResult.HasError = true;
            errors.UnknownError = "Query returned no data from Google Analytics";

            gaResult.Errors = errors;

        }

        return objectToXML(gaResult);


    }

    private static String objectToXML(IAPIResult gaResult){
        String result = "";
        try {

            JAXBContext contextObj = JAXBContext.newInstance(gaResult.getClass());

            Marshaller marshallerObj = contextObj.createMarshaller();
            marshallerObj.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

            StringWriter sw = new StringWriter();

            marshallerObj.marshal(gaResult, sw);
            result = sw.getBuffer().toString();

            return result;

        } catch (Exception ex) {
            ex.printStackTrace();
            result = ex.getMessage();
            return result;
        }
    }

    private static void writeXMLFile(String filePath, String profileId, String xml){
        try {

            Date date = new Date();
            SimpleDateFormat dateFormat = new SimpleDateFormat("MMddYYYY");
            String fileName = filePath + "_" + dateFormat.format(date) + "_" + profileId + ".xml";

            FileWriter fw = new FileWriter(fileName);
            BufferedWriter bw = new BufferedWriter(fw);

            bw.write(xml);
            bw.flush();
            bw.close();
        }catch (Exception ex){
            ex.printStackTrace();
        }

    }

    /**
     * Prints all the rows of data returned by the API.
     *
     * @param gaData the data returned from the API.
     */
    private static void printDataTable(GaData gaData) {
        if (gaData.getTotalResults() > 0) {
            System.out.println("Data Table:");

            // Print the column names.
            for (GaData.ColumnHeaders header : gaData.getColumnHeaders()) {
                System.out.format("%-32s", header.getName());
            }
            System.out.println();

            // Print the rows of data.
            for (List<String> rowValues : gaData.getRows()) {
                for (String value : rowValues) {
                    System.out.format("%-32s", value);
                }
                System.out.println();
            }
        } else {
            System.out.println("No data");
        }
    }

    private static void printDataTable(McfData mcfData) {
        if (mcfData.getTotalResults() > 0) {
            System.out.println("Data Table:");

            // Print the column names.
            for (McfData.ColumnHeaders header : mcfData.getColumnHeaders()) {
                System.out.format("%-32s", header.getName());
            }
            System.out.println();

            // Print the rows of data.
            for (List<McfData.Rows> rowValues : mcfData.getRows()) {
                for (McfData.Rows value : rowValues) {
                    System.out.format("%-32s", value.getPrimitiveValue());
                }
                System.out.println();
            }
        } else {
            System.out.println("No data");
        }
    }


    private static void printQueryInfo(GaData gaData) {
        GaData.Query query = gaData.getQuery();

        System.out.println("Query Info:");
        System.out.println("Ids: " + query.getIds());
        System.out.println("Start Date: " + query.getStartDate());
        System.out.println("End Date: " + query.getEndDate());
        System.out.println("Metrics: " + query.getMetrics()); // List
        System.out.println("Dimensions: " + query.getDimensions()); // List
        System.out.println("Sort: " + query.getSort()); // List
        System.out.println("Segment: " + query.getSegment());
        System.out.println("Filters: " + query.getFilters());
        System.out.println("Start Index: " + query.getStartIndex());
        System.out.println("Max Results: " + query.getMaxResults());
    }

    private static void printQueryInfo(McfData gaData) {
        McfData.Query query = gaData.getQuery();

        System.out.println("Query Info:");
        System.out.println("Ids: " + query.getIds());
        System.out.println("Start Date: " + query.getStartDate());
        System.out.println("End Date: " + query.getEndDate());
        System.out.println("Metrics: " + query.getMetrics()); // List
        System.out.println("Dimensions: " + query.getDimensions()); // List
        System.out.println("Sort: " + query.getSort()); // List
        System.out.println("Segment: " + query.getSegment());
        System.out.println("Filters: " + query.getFilters());
        System.out.println("Start Index: " + query.getStartIndex());
        System.out.println("Max Results: " + query.getMaxResults());
    }


    private void printTotalsForAllResults(GaData gaData) {
        Map<String, String> totalsMap = gaData.getTotalsForAllResults();

        for (Map.Entry<String,String> entry : totalsMap.entrySet()) {
            System.out.println(entry.getKey() + " : " + entry.getValue());
        }
    }

    private void printTotalsForAllResults(McfData mcfData) {
        Map<String, String> totalsMap = mcfData.getTotalsForAllResults();

        for (Map.Entry<String,String> entry : totalsMap.entrySet()) {
            System.out.println(entry.getKey() + " : " + entry.getValue());
        }
    }

}
